﻿using System;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Web;
using Kooboo.Globalization;
using System.Text.RegularExpressions;
using Kooboo.Commerce.Contexts.ShopSettings;

namespace Kooboo.Commerce
{
    public enum ImageCategory
    {
        BrandLogo = 1,
        CategoryPhoto = 2,
        ProductThumbnail = 3,
        ProductImage = 4
    }

    public class ImageManager
    {
        private readonly string originalDir;
        private readonly string thumbnailDir;
        private readonly int thumbnailWidth;
        private readonly int thumbnailHeight;
        private readonly ImageCategory _ImageCategory;

        public ImageManager(ImageCategory imageCategory)
        {
            this._ImageCategory = imageCategory;

            var host = new ServiceHost();

           
            thumbnailHeight = (int)host.GetShopSettings().ImageSettings.Thumbnail.Height;
            thumbnailWidth = (int)host.GetShopSettings().ImageSettings.Thumbnail.Width;
            switch (imageCategory)
            {
                case ImageCategory.BrandLogo:
                    originalDir = @"~/images/brand/";
                    thumbnailDir = @"~/images/brand/thumbnails/";
                    //thumbnailWidth = 100;
                    //thumbnailHeight = 100;
                    break;
                case ImageCategory.CategoryPhoto:
                    originalDir = @"~/images/category/";
                    thumbnailDir = @"~/images/category/thumbnails/";
                    //thumbnailWidth = 100;
                    //thumbnailHeight = 100;
                    break;
                case ImageCategory.ProductThumbnail:
                    originalDir = @"~/images/product/";
                    thumbnailDir = @"~/images/product/thumbnails/";
                    //thumbnailWidth = 100;
                    //thumbnailHeight = 100;
                    break;
                case ImageCategory.ProductImage:
                    originalDir = @"~/images/product/";
                    thumbnailDir = @"~/images/product/thumbnails/";
                    //thumbnailWidth = 100;
                    //thumbnailHeight = 100;
                    break;
                default:
                    //thumbnailWidth = 100;
                    //thumbnailHeight = 100;
                    break;
            }
        }

        #region Upload
        public string Upload(HttpPostedFileBase file, string fileName)
        {
            System.Drawing.Image originalImage = null;
            System.Drawing.Bitmap finalImage = null;
            System.Drawing.Graphics graphic = null;
            MemoryStream ms = null;

            try
            {
                // Get the data
                var extension = Path.GetExtension(file.FileName);

                // Retrieve the uploaded image
                originalImage = System.Drawing.Image.FromStream(file.InputStream);

                var saveDir = HttpContext.Current.Server.MapPath(originalDir);
                fileName = GenerateFileName(fileName, extension);

                originalImage.Save(Path.Combine(saveDir, fileName + extension));

                // Calculate the new width and height
                int width = originalImage.Width;
                int height = originalImage.Height;
                int newWidth, newHeight;

                float targetRatio = (float)thumbnailWidth / (float)thumbnailHeight;
                float imageRatio = (float)width / (float)height;

                if (targetRatio > imageRatio)
                {
                    newHeight = thumbnailHeight;
                    newWidth = (int)Math.Floor(imageRatio * (float)thumbnailHeight);
                }
                else
                {
                    newHeight = (int)Math.Floor((float)thumbnailWidth / imageRatio);
                    newWidth = thumbnailWidth;
                }

                newWidth = newWidth > thumbnailWidth ? thumbnailWidth : newWidth;
                newHeight = newHeight > thumbnailHeight ? thumbnailHeight : newHeight;


                finalImage = new System.Drawing.Bitmap(thumbnailWidth, thumbnailHeight);
                graphic = System.Drawing.Graphics.FromImage(finalImage);
                using (var solidBrush = new System.Drawing.SolidBrush(Color.Transparent))
                {
                    graphic.FillRectangle(solidBrush, new System.Drawing.Rectangle(0, 0, thumbnailWidth, thumbnailHeight));
                }
                int paste_x = (thumbnailWidth - newWidth) / 2;
                int paste_y = (thumbnailHeight - newHeight) / 2;
                graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphic.Clear(Color.Transparent);

                graphic.DrawImage(originalImage, paste_x, paste_y, newWidth, newHeight);

                var thumbnailSaveDir = HttpContext.Current.Server.MapPath(thumbnailDir);
                if (!Directory.Exists(thumbnailSaveDir))
                {
                    Directory.CreateDirectory(thumbnailSaveDir);
                }

                var thumbnailPath = Path.Combine(thumbnailSaveDir, fileName + extension);
                finalImage.Save(thumbnailPath);

                HttpContext.Current.Response.StatusCode = 200;
                return fileName + extension;
            }
            catch
            {
                // If any kind of error occurs return a 500 Internal Server error
                HttpContext.Current.Response.StatusCode = 500;
                return "An error occured";
            }
            finally
            {
                if (finalImage != null) { finalImage.Dispose(); }
                if (graphic != null) { graphic.Dispose(); }
                if (originalImage != null) { originalImage.Dispose(); }
                if (ms != null) { ms.Close(); }
            }
        }
        #endregion

        public string GetThumbnailPath(string fileName)
        {
            return Path.Combine(thumbnailDir, fileName);
        }

        public string GetOriginalPath(string fileName)
        {
            return Path.Combine(originalDir, fileName);
        }


        public string GenerateFileName(string fileName, string extension)
        {
            if (string.IsNullOrWhiteSpace(fileName))
            {
                fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            }
            else
            {
                fileName = FileNameFilter(fileName);
            }

            var saveDir = HttpContext.Current.Server.MapPath(originalDir);
            if (!Directory.Exists(saveDir))
            {
                Directory.CreateDirectory(saveDir);
            }
            var i = 1;
            string oldName = fileName;
            while (System.IO.File.Exists(Path.Combine(saveDir, fileName + extension)))
            {
                fileName = String.Format("{0}-{1}", oldName, i++);
            }

            return fileName;
        }

        public string Rename(string oldName, string newName)
        {
            if (String.IsNullOrWhiteSpace(oldName))
            {
                throw new ArgumentNullException("oldName", "the oldName can't be null");
            }

            if (String.IsNullOrWhiteSpace(newName))
            {
                throw new ArgumentNullException("newName", "the newName can't be null");
            }

            newName = FileNameFilter(newName);
            Regex regex = new Regex(@"(-\d+)?.[A-Za-z]+$");
            if (regex.Replace(oldName, "") == newName)
            {
                return oldName;
            }

            var extension = Path.GetExtension(oldName);
            newName = GenerateFileName(newName, extension) + extension;

            var thumbnailPath = HttpContext.Current.Server.MapPath(GetThumbnailPath(oldName));
            var targetThumbnailPath = HttpContext.Current.Server.MapPath(GetThumbnailPath(newName));
            if (File.Exists(thumbnailPath))
            {
                File.Move(thumbnailPath, targetThumbnailPath);
            }

            var originalPath = HttpContext.Current.Server.MapPath(GetOriginalPath(oldName));
            var targetOriginalPath = HttpContext.Current.Server.MapPath(GetOriginalPath(newName));
            if (File.Exists(originalPath))
            {
                File.Move(originalPath, targetOriginalPath);
            }

            return newName;
        }

        public void Delete(string fileName)
        {
            if (string.IsNullOrWhiteSpace(fileName))
            {
                return;
            }

            var path = Path.Combine(thumbnailDir, fileName);
            if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(path)))
            {
                System.IO.File.Delete(HttpContext.Current.Server.MapPath(path));
            }

            path = Path.Combine(originalDir, fileName);
            if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(path)))
            {
                System.IO.File.Delete(HttpContext.Current.Server.MapPath(path));
            }
        }

        public byte[] GenerateNotExistImage()
        {
            using (System.Drawing.Bitmap image = new System.Drawing.Bitmap(thumbnailWidth, thumbnailHeight))
            {

                Graphics graphic = Graphics.FromImage(image);

                try
                {
                    graphic.Clear(Color.White);

                    using (Font font = new System.Drawing.Font("Arial", 11, System.Drawing.FontStyle.Regular))
                    {
                        using (System.Drawing.Drawing2D.LinearGradientBrush brush =
                             new System.Drawing.Drawing2D.LinearGradientBrush(
                                 new Rectangle(0, 0, image.Width, image.Height), Color.FromArgb(207, 207, 207), Color.FromArgb(207, 207, 207), 1.2f, true))
                        {
                            graphic.DrawString("Image".Localize(), font, brush, 25, 25);
                            graphic.DrawString("Not Available".Localize(), font, brush, 5, 50);
                        }
                    }
                    using (var pen = new Pen(Color.White))
                    {
                        graphic.DrawRectangle(pen, 0, 0, image.Width, image.Height);
                    }
                }
                finally
                {
                    graphic.Dispose();
                }


                using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
                {
                    image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                    return memoryStream.ToArray();
                }
                
            }
        }

        public string FileNameFilter(string fileName)
        {
            return fileName.Replace(' ', '-').Replace('>', '-')
                .Replace('<', '-').Replace(',', '-').Replace(';', '-')
                .Replace('\\', '-').Replace('/', '-').Replace('~', '-')
                .Replace('*', '-').Replace('?', '-').Replace('|', '-')
                .Replace(':', '-').Replace('"', '-').Replace('&', '-');
        }

    }
}